#include "StdAfx.h"
#include ".\aphttpproxy.h"

#define RECV_BUFFER_SIZE 65536

#pragma comment(lib, "Ws2_32.lib")

static int GetContentLength(const char *httpHeader);
static int GetHttpHeader(SOCKET sckDest,char *str);

apHTTPProxy::apHTTPProxy(void)
{
}

apHTTPProxy::~apHTTPProxy(void)
{
}

bool apHTTPProxy::Init(const char *proxy_ipaddr, int proxy_port)
{
	m_proxy_addr = proxy_ipaddr;
	m_proxy_port = proxy_port;

	return start();
}

void apHTTPProxy::thread_proc()
{
	apLog::print(0, apLog::info, "apHTTPProxy thread started...");

	bool ret;
	CActiveSocket *pClient = NULL;
	char buf[RECV_BUFFER_SIZE] = {0};
	int iRetval;
	int send_size;
	const short listen_port = 80;//8089

	ret = m_server.Initialize();
	if(!ret)
	{
		apLog::print(0, apLog::error, "failed to initialize");
		return;
	}
	ret = m_server.Listen((uint8 *)"127.0.0.1", listen_port);//
	if(!ret)
	{
		apLog::print(0, apLog::error, "failed to listen");
		return;
	}

	apLog::print(0, apLog::info, "%s:%d listening...", m_server.GetServerAddr(), listen_port);
	CActiveSocket *proxy = NULL;
	while(!isexit(10))
	{
		pClient = m_server.Accept();
		if(!pClient)
		{
			apLog::print(0, apLog::error, "failed to accept");
			goto cleanup;
		}
		apLog::print(0, apLog::info, "new client %s:%hu connected",
			m_server.GetClientAddr(), m_server.GetClientPort());
		
		apLog::print(0, apLog::info, "receiving client request...");
		//recv from client
		iRetval = pClient->Receive2((uint8 *)buf, RECV_BUFFER_SIZE);
		if(iRetval < 0)
		{
			apLog::print(0, apLog::error, "failed to recv");
			goto cleanup;
		}
		if(iRetval == 0)
		{
			apLog::print(0, apLog::error, "recv size 0");
			goto cleanup;
		}
		*(buf + iRetval) = '\0';
		apLog::print(0, apLog::info, "recv from client(%d)\n%s", iRetval, buf);

		//proxy processing
		proxy = new CActiveSocket;
		proxy->Initialize();
		apLog::print(0, apLog::info, "opening proxy %s:%d...", m_proxy_addr.c_str(), m_proxy_port);
		ret = proxy->Open((uint8 *)m_proxy_addr.c_str(), m_proxy_port);
		if(!ret)
		{
			apLog::print(0, apLog::error, "failed to connect to proxy");
			goto cleanup;
		}
		apLog::print(0, apLog::info, "sending proxy request...");
		iRetval = proxy->Send((uint8 *)buf, iRetval);
		if(iRetval < 0)
		{
			apLog::print(0, apLog::error, "failed to send to proxy");
			goto cleanup;
		}
		apLog::print(0, apLog::info, "proxy request sent size %d", iRetval);

		apLog::print(0, apLog::info, "receiving proxy response...");
		iRetval = proxy->Receive2((uint8 *)buf, RECV_BUFFER_SIZE);
		if(iRetval < 0)
		{
			apLog::print(0, apLog::error, "failed to recv ack from proxy");
			goto cleanup;
		}
		*(buf + iRetval) = '\0';
		if(!strstr(buf, "200"))
		{
			apLog::print(0, apLog::warning, "proxy response is not 200\n%s", buf);
			goto cleanup;
		}
		int content_len = GetContentLength(buf);
		if(content_len < 0)
		{
			apLog::print(0, apLog::warning, "content len %d\n%s",
				content_len, buf);
		}

		//send to client 1
		send_size = iRetval;
		iRetval = pClient->Send((uint8 *)buf, send_size);
		if(iRetval < 0)
		{
			apLog::print(0, apLog::error, "failed to send to client");
			goto cleanup;
		}
		apLog::print(0, apLog::info, "send response to client s1(%d)\n%s",
			send_size, buf);

		int to_reveive;
		if(content_len < 0)
			to_reveive = RECV_BUFFER_SIZE;
		else
			to_reveive = content_len;
		iRetval = proxy->Receive2((uint8 *)buf, to_reveive);
		if(iRetval < 0)
		{
			apLog::print(0, apLog::error, "failed to recv proxy content");
			goto cleanup;
		}
		*(buf + iRetval) = '\0';

		//send to client 2
		send_size = iRetval;
		iRetval = pClient->Send((uint8 *)buf, send_size);
		if(iRetval < 0)
		{
			apLog::print(0, apLog::error, "failed to send to client");
			goto cleanup;
		}
		apLog::print(0, apLog::info, "send response to client s2(%d)\n%s\n\n\n", send_size, buf);
cleanup:
		if(proxy)
		{
			proxy->Close();
			delete proxy;
			proxy = NULL;
		}
		if(pClient)
		{
			pClient->Close();
			delete pClient;
			pClient = NULL;
		}
	}
	apLog::print(0, apLog::info, "apHTTPProxy thread exited");
}

static int GetContentLength(const char *httpHeader)
{
	char *pos = NULL;
	const char* item = "Content-Length: ";
	pos = strstr(httpHeader, item);
	if(!pos)
		return -1;
	char temp[30] = {0};
	char *end = pos + strlen(item);
	int len = 0;
	while(*(end++) != '\n')
	{
		len++;
	}
	strncpy(temp, pos + strlen(item), len);
	return atoi(temp);
}

static int GetHttpHeader(SOCKET sckDest,char *str)
{
	/*BOOL m_bResponsed=0;
	int m_nResponseHeaderSize;
	if(!m_bResponsed)
	{
		char c = 0;
		int nIndex = 0;
		BOOL bEndResponse = FALSE;
		while(!bEndResponse && nIndex < 1024)
		{
			recv(sckDest,&c,1,0);
			str[nIndex++] = c;
			if(nIndex >= 4)
			{
				if(str[nIndex - 4] == '\r' && str[nIndex - 3] == '\n'
					&& str[nIndex - 2] == '\r' && str[nIndex - 1] == '\n')
					bEndResponse = TRUE;
			}
		}
		m_nResponseHeaderSize = nIndex;
		m_bResponsed = TRUE;
	}
	return m_nResponseHeaderSize;*/
	str = "xxx";
	return 128;
}
